Implement Phase 1: tool-calling loop, conversation history, CI/CD, docs, resilience, observability#3
Implement Phase 1: tool-calling loop, conversation history, CI/CD, docs, resilience, observability#3
Conversation
…ion history Introduces ContentBlock (with ContentBlockKind enum) and ChatMessage sealed records, registers them in ProtocolJsonContext, and adds three roundtrip serialization tests covering text, tool-use, and tool-result blocks. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…vent with tool-use fields Add ProviderToolDefinition to Protocol (decoupled from Tools), extend ProviderRequest with Messages/Tools/MaxTokens, extend ProviderEvent with BlockType/ToolUseId/ToolName/ToolInputJson, and add InputSchemaJson to ToolDefinition. All new fields are optional with null defaults so existing call sites compile without modification. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ts message history - Add ToolUse factory method to ProviderStreamEventFactory - Update AnthropicSdkStreamAdapter to detect ContentBlockStart/Stop and accumulate InputJsonDelta into tool_use events - Create AnthropicMessageBuilder to map ChatMessage[]/ProviderToolDefinition[] to Anthropic SDK params (MessageParam[], ToolUnion[]) - Update AnthropicProvider.StartStreamAsync to use message history, tools, and MaxTokens from ProviderRequest when Messages is set - Add ToolUseStreamAdapterTests covering factory, stream adapter, and builder behaviors Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ge history - Update OpenAiMeaiStreamAdapter to detect FunctionCallContent in stream updates and emit ToolUse provider events - Add OpenAiMessageBuilder to map ProtocolChatMessage[]/ProviderToolDefinition[] to MEAI types (uses AIFunctionFactory.CreateDeclaration for tool schemas) - Update OpenAiCompatibleProvider to use message history and tools from ProviderRequest when present, falling back to single-prompt path - Add 5 new unit tests covering role mapping, FunctionCallContent, FunctionResultContent, tool building, and null-schema handling Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…olExecutor Implements ToolCallDispatcher that dispatches ProviderEvent tool-use requests through IToolExecutor, publishes ToolStartedEvent and ToolCompletedEvent runtime events, and returns a ContentBlock for feeding results back to the provider. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add multi-iteration tool-calling loop that streams provider responses, detects tool-use events, dispatches them via ToolCallDispatcher, feeds results back as conversation messages, and resumes until the model stops requesting tools or MaxToolIterations is reached. - Create AgentLoopOptions for loop configuration (max iterations, max tokens) - Update ProviderBackedAgentKernel with tool-calling loop and backward-compat overload - Update AgentFrameworkBridge to accept IToolRegistry, build ToolExecutionContext, map tool definitions, and collect tool results - Add tool_call_roundtrip mock scenario to DeterministicMockModelProvider - Add parity test verifying the loop executes end-to-end Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… context window management Introduces ConversationHistoryAssembler and ContextWindowManager to enable multi-turn conversations across session resume. Prior completed turns are read from the event store, assembled into ChatMessage[] pairs, truncated to a 100k-token budget, and threaded through PromptExecutionContext → AgentRunContext → ProviderBackedAgentKernel so the provider receives full context on every request. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add NuGet package metadata including author, company, license, repository, and per-package descriptions to all publishable source projects. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds SharpClawActivitySource and SharpClawMeterSource as central OTel instrumentation points; TurnActivityScope and ProviderActivityScope wrap turn/provider execution in Activity spans; NdjsonTraceFileSink writes completed spans as NDJSON for offline analysis. DefaultTurnRunner and ProviderBackedAgentKernel are wired to emit spans and record metrics. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Wraps IModelProvider registrations in ResilientProviderDecorator which retries transient failures (HttpRequestException 5xx, TaskCanceledException, IOException) with exponential backoff and jitter, honours Retry-After on 429 responses, and opens a circuit breaker after a configurable consecutive- failure threshold. All behaviour is driven by ProviderResilienceOptions and can be disabled via Enabled=false. Four unit tests cover retry-then-succeed, non-transient pass-through, circuit open, and probe-after-break-duration. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR advances SharpClaw Code from a basic streaming wrapper to a more complete agent runtime by adding structured conversation history, a multi-iteration tool-calling loop across providers, resilience/observability primitives, plus initial CI/CD, docs, and examples.
Changes:
- Introduces protocol/runtime support for multi-turn conversation history (
ChatMessage/ContentBlock) and context-window truncation. - Implements provider tool-use extraction + a tool-calling loop (
ProviderBackedAgentKernel+ToolCallDispatcher) with parity coverage. - Adds provider resilience (retry + circuit breaker) and baseline telemetry (OpenTelemetry spans + metrics) plus CI/release workflows and getting-started/integration docs & examples.
Reviewed changes
Copilot reviewed 78 out of 78 changed files in this pull request and generated 14 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/SharpClaw.Code.UnitTests/SharpClaw.Code.UnitTests.csproj | Adds Agents project reference so unit tests can cover new internal orchestration. |
| tests/SharpClaw.Code.UnitTests/Runtime/ConversationHistoryAssemblerTests.cs | Unit tests for assembling chat history from runtime events. |
| tests/SharpClaw.Code.UnitTests/Runtime/ContextWindowManagerTests.cs | Unit tests for token-budget truncation rules. |
| tests/SharpClaw.Code.UnitTests/Providers/ToolUseStreamAdapterTests.cs | Verifies streaming tool-use extraction and message/tool mapping for Anthropic + OpenAI-compatible adapters. |
| tests/SharpClaw.Code.UnitTests/Providers/ResilienceTests.cs | Tests retries and circuit breaker behavior for the resilience decorator. |
| tests/SharpClaw.Code.UnitTests/Protocol/ChatMessageSerializationTests.cs | Roundtrip serialization tests for new protocol message/content block types. |
| tests/SharpClaw.Code.UnitTests/Agents/ToolCallDispatcherTests.cs | Tests bridging provider tool-use events to tool execution + runtime events. |
| tests/SharpClaw.Code.ParityHarness/ParityScenarioTests.cs | Adds parity scenario to validate end-to-end tool-calling loop behavior. |
| tests/SharpClaw.Code.ParityHarness/ParityScenarioIds.cs | Registers new parity scenario ID. |
| tests/SharpClaw.Code.MockProvider/ParityProviderScenario.cs | Adds mock-provider scenario constant for tool roundtrip. |
| tests/SharpClaw.Code.MockProvider/DeterministicMockModelProvider.cs | Simulates tool-use then final response across loop iterations. |
| src/SharpClaw.Code.Web/SharpClaw.Code.Web.csproj | Adds NuGet package metadata description. |
| src/SharpClaw.Code.Tools/SharpClaw.Code.Tools.csproj | Adds NuGet package metadata description. |
| src/SharpClaw.Code.Tools/Models/ToolDefinition.cs | Extends tool definition to include optional input schema JSON. |
| src/SharpClaw.Code.Telemetry/SharpClaw.Code.Telemetry.csproj | Adds NuGet package metadata description. |
| src/SharpClaw.Code.Telemetry/Metrics/SharpClawMeterSource.cs | Introduces central Meter + counters/histograms for runtime metrics. |
| src/SharpClaw.Code.Telemetry/Export/NdjsonTraceFileSink.cs | Adds NDJSON Activity span export sink for offline trace analysis. |
| src/SharpClaw.Code.Telemetry/Diagnostics/TurnActivityScope.cs | Adds Activity scope for turns with key tags and error reporting. |
| src/SharpClaw.Code.Telemetry/Diagnostics/SharpClawActivitySource.cs | Defines shared ActivitySource for SharpClaw tracing. |
| src/SharpClaw.Code.Telemetry/Diagnostics/ProviderActivityScope.cs | Adds Activity scope for provider calls with token tags. |
| src/SharpClaw.Code.Skills/SharpClaw.Code.Skills.csproj | Adds NuGet package metadata description. |
| src/SharpClaw.Code.Sessions/SharpClaw.Code.Sessions.csproj | Adds NuGet package metadata description. |
| src/SharpClaw.Code.Runtime/Turns/DefaultTurnRunner.cs | Wraps turn execution with tracing + metrics and propagates conversation history. |
| src/SharpClaw.Code.Runtime/SharpClaw.Code.Runtime.csproj | Adds NuGet package metadata description. |
| src/SharpClaw.Code.Runtime/Context/PromptExecutionContext.cs | Adds conversation-history field to prompt execution context. |
| src/SharpClaw.Code.Runtime/Context/PromptContextAssembler.cs | Reads session event log and assembles/truncates conversation history for providers. |
| src/SharpClaw.Code.Runtime/Context/ConversationHistoryAssembler.cs | Implements event-log → ordered user/assistant message assembly. |
| src/SharpClaw.Code.Runtime/Context/ContextWindowManager.cs | Implements token-budget truncation for chat history. |
| src/SharpClaw.Code.Providers/SharpClaw.Code.Providers.csproj | Adds package description + internal visibility for unit tests. |
| src/SharpClaw.Code.Providers/Resilience/ResilientProviderDecorator.cs | Adds retry/backoff + basic circuit breaker around provider calls. |
| src/SharpClaw.Code.Providers/ProvidersServiceCollectionExtensions.cs | Wires resilience options + wraps providers conditionally. |
| src/SharpClaw.Code.Providers/OpenAiCompatibleProvider.cs | Adds support for request.Messages/tools/max tokens for MEAI-based provider. |
| src/SharpClaw.Code.Providers/Internal/ProviderStreamEventFactory.cs | Adds provider event factory method for tool-use events. |
| src/SharpClaw.Code.Providers/Internal/OpenAiMessageBuilder.cs | Maps SharpClaw chat/tool definitions to MEAI message/tool types. |
| src/SharpClaw.Code.Providers/Internal/OpenAiMeaiStreamAdapter.cs | Emits tool-use ProviderEvents from MEAI streaming function calls. |
| src/SharpClaw.Code.Providers/Internal/AnthropicSdkStreamAdapter.cs | Accumulates tool-use blocks from Anthropic streaming events. |
| src/SharpClaw.Code.Providers/Internal/AnthropicMessageBuilder.cs | Maps SharpClaw chat/tool definitions to Anthropic SDK message/tool types. |
| src/SharpClaw.Code.Providers/Configuration/ProviderResilienceOptions.cs | Adds resilience configuration options (retries, timeouts, circuit breaker). |
| src/SharpClaw.Code.Providers/AnthropicProvider.cs | Adds support for request.Messages/tools/max tokens via Anthropic SDK types. |
| src/SharpClaw.Code.Protocol/SharpClaw.Code.Protocol.csproj | Adds NuGet package metadata description. |
| src/SharpClaw.Code.Protocol/Serialization/ProtocolJsonContext.cs | Adds source-gen JSON serialization support for new protocol models. |
| src/SharpClaw.Code.Protocol/Models/ProviderToolDefinition.cs | Introduces provider-facing tool definition contract. |
| src/SharpClaw.Code.Protocol/Models/ProviderRequest.cs | Extends provider request to include messages, tools, and max tokens. |
| src/SharpClaw.Code.Protocol/Models/ProviderEvent.cs | Extends provider events with tool-use metadata fields. |
| src/SharpClaw.Code.Protocol/Models/ContentBlock.cs | Introduces typed content blocks (text/tool_use/tool_result). |
| src/SharpClaw.Code.Protocol/Models/ChatMessage.cs | Introduces chat message model holding ordered content blocks. |
| src/SharpClaw.Code.Plugins/SharpClaw.Code.Plugins.csproj | Adds NuGet package metadata description. |
| src/SharpClaw.Code.Permissions/SharpClaw.Code.Permissions.csproj | Adds NuGet package metadata description. |
| src/SharpClaw.Code.Memory/SharpClaw.Code.Memory.csproj | Adds NuGet package metadata description. |
| src/SharpClaw.Code.Mcp/SharpClaw.Code.Mcp.csproj | Adds NuGet package metadata description. |
| src/SharpClaw.Code.Infrastructure/SharpClaw.Code.Infrastructure.csproj | Adds NuGet package metadata description. |
| src/SharpClaw.Code.Git/SharpClaw.Code.Git.csproj | Adds NuGet package metadata description. |
| src/SharpClaw.Code.Commands/SharpClaw.Code.Commands.csproj | Adds NuGet package metadata description. |
| src/SharpClaw.Code.Cli/SharpClaw.Code.Cli.csproj | Adds NuGet package metadata description. |
| src/SharpClaw.Code.Agents/SharpClaw.Code.Agents.csproj | Adds options dependency, InternalsVisibleTo, and package description. |
| src/SharpClaw.Code.Agents/Services/AgentFrameworkBridge.cs | Maps tool registry → provider tools, builds tool execution context, and returns tool events/results. |
| src/SharpClaw.Code.Agents/Models/AgentRunContext.cs | Adds conversation history to agent run context. |
| src/SharpClaw.Code.Agents/Internal/ToolCallDispatcher.cs | Executes tool calls, publishes started/completed events, returns tool-result content blocks. |
| src/SharpClaw.Code.Agents/Internal/ProviderInvocationResult.cs | Extends provider invocation result to include tool results/events. |
| src/SharpClaw.Code.Agents/Internal/ProviderBackedAgentKernel.cs | Implements multi-iteration tool-calling loop and provider span/metrics. |
| src/SharpClaw.Code.Agents/Configuration/AgentLoopOptions.cs | Adds configuration for loop iterations and per-request token cap. |
| src/SharpClaw.Code.Agents/AgentsServiceCollectionExtensions.cs | Registers loop options and tool dispatcher in DI. |
| src/SharpClaw.Code.Acp/SharpClaw.Code.Acp.csproj | Adds NuGet package metadata description. |
| examples/WebApiAgent/WebApiAgent.csproj | Adds minimal ASP.NET Core agent example project. |
| examples/WebApiAgent/Program.cs | Implements minimal HTTP chat endpoint using SharpClaw runtime. |
| examples/WebApiAgent/appsettings.json | Provides example configuration for provider selection + logging. |
| examples/MinimalConsoleAgent/Program.cs | Adds minimal console agent example entry point. |
| examples/MinimalConsoleAgent/MinimalConsoleAgent.csproj | Adds minimal console agent example project file. |
| examples/MinimalConsoleAgent/appsettings.json | Provides example configuration for provider selection + logging. |
| examples/McpToolAgent/Program.cs | Adds example showing custom tool registration and invocation. |
| examples/McpToolAgent/McpToolAgent.csproj | Adds custom tool agent example project file. |
| examples/McpToolAgent/EchoTool.cs | Implements a simple custom echo tool using SharpClaw tool base class. |
| examples/McpToolAgent/appsettings.json | Provides example configuration for provider selection + logging. |
| docs/getting-started.md | Adds getting-started guide with build/run/config instructions. |
| docs/agent-framework-integration.md | Adds guide describing SharpClaw layering on Microsoft Agent Framework. |
| Directory.Build.props | Adds shared NuGet metadata (authors/license/repo URLs). |
| .github/workflows/release.yml | Adds tag-driven NuGet package publish workflow. |
| .github/workflows/ci.yml | Adds multi-OS build/test workflow with coverage artifact upload. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| var messages = new List<ChatMessage>(); | ||
| if (!string.IsNullOrWhiteSpace(request.Instructions)) | ||
| { | ||
| messages.Add(new ChatMessage("system", [new ContentBlock(ContentBlockKind.Text, request.Instructions, null, null, null, null)])); | ||
| } |
There was a problem hiding this comment.
The tool-calling loop prepends a ChatMessage with role == "system" and also passes the same instructions via ProviderRequest.SystemPrompt. Anthropic only supports user/assistant roles and AnthropicMessageBuilder maps any non-assistant role to user, so this will turn system instructions into an extra user message (and potentially duplicate the system prompt). Consider removing the explicit "system" ChatMessage from the shared message list and letting each provider adapter apply SystemPrompt appropriately (or explicitly filtering out system-role messages for Anthropic).
| var messages = new List<ChatMessage>(); | |
| if (!string.IsNullOrWhiteSpace(request.Instructions)) | |
| { | |
| messages.Add(new ChatMessage("system", [new ContentBlock(ContentBlockKind.Text, request.Instructions, null, null, null, null)])); | |
| } | |
| // Do not add request.Instructions as a shared "system" chat message here. | |
| // Provider adapters should apply system instructions via ProviderRequest.SystemPrompt | |
| // so providers that do not support a native "system" role (for example Anthropic) | |
| // do not receive duplicated or remapped instruction turns. | |
| var messages = new List<ChatMessage>(); |
|
|
||
| await foreach (var providerEvent in stream.Events.WithCancellation(cancellationToken)) | ||
| for (var iteration = 0; iteration < options.MaxToolIterations; iteration++) | ||
| { |
There was a problem hiding this comment.
terminalUsage is declared outside the iteration loop and never reset per iteration. If a later provider call returns a terminal event without Usage (or Usage=null), the loop will reuse the previous iteration's usage when setting ProviderActivityScope tags and when returning the final UsageSnapshot, producing incorrect telemetry/usage reporting. Track usage per iteration (reset to null at loop start) and only promote it to the overall terminal usage when the current iteration provides it.
| { | |
| { | |
| terminalUsage = null; |
| providerSw.Stop(); | ||
| providerScope.SetCompleted(terminalUsage?.InputTokens, terminalUsage?.OutputTokens); | ||
| SharpClawMeterSource.ProviderDuration.Record(providerSw.Elapsed.TotalMilliseconds); |
There was a problem hiding this comment.
ProviderActivityScope.SetCompleted is called with terminalUsage which can reflect a previous iteration (since terminalUsage isn't iteration-scoped). This can attach incorrect token counts to spans for calls that didn't emit usage. Use an iteration-local usage variable for span tagging, and separately maintain the final/last-known usage for the overall ProviderInvocationResult.
| /// <list type="number"> | ||
| /// <item>The system message (role == "system") is always kept.</item> | ||
| /// <item>The most-recent user message is always kept.</item> | ||
| /// <item>Oldest non-system messages are dropped until the budget is satisfied.</item> | ||
| /// </list> |
There was a problem hiding this comment.
The XML docs say the "most-recent user message" is always kept, but the implementation actually guarantees only the most recent non-system message is kept (which may be an assistant message, and the code does not look for the most recent user role specifically). Either update the documentation to match the behavior or adjust the truncation logic to explicitly preserve the most recent user message.
| var toolName = toolUseEvent.ToolName ?? string.Empty; | ||
| var toolInputJson = toolUseEvent.ToolInputJson ?? "{}"; | ||
| var toolUseId = toolUseEvent.ToolUseId ?? string.Empty; |
There was a problem hiding this comment.
Defaulting ToolName/ToolUseId to empty strings can lead to publishing ToolStartedEvent/ToolCompletedEvent with empty identifiers and then invoking the tool executor with an empty tool name. It would be safer to validate these fields on toolUseEvent and return an error tool-result block (and/or a classified runtime event) without calling the executor when required metadata is missing.
| var toolName = toolUseEvent.ToolName ?? string.Empty; | |
| var toolInputJson = toolUseEvent.ToolInputJson ?? "{}"; | |
| var toolUseId = toolUseEvent.ToolUseId ?? string.Empty; | |
| global::System.ArgumentException.ThrowIfNullOrWhiteSpace(toolUseEvent.ToolName); | |
| global::System.ArgumentException.ThrowIfNullOrWhiteSpace(toolUseEvent.ToolUseId); | |
| var toolName = toolUseEvent.ToolName; | |
| var toolInputJson = toolUseEvent.ToolInputJson ?? "{}"; | |
| var toolUseId = toolUseEvent.ToolUseId; |
| - Placeholder response when stream is empty | ||
|
|
||
| **Loop Configuration:** Controlled by `AgentLoopOptions`: | ||
| - `MaxToolIterations` — maximum rounds (default ~10) |
There was a problem hiding this comment.
The documented default for AgentLoopOptions.MaxToolIterations is "~10", but the implementation sets the default to 25. Please update the doc to reflect the actual default (or update AgentLoopOptions if 10 is the intended default).
| - `MaxToolIterations` — maximum rounds (default ~10) | |
| - `MaxToolIterations` — maximum rounds (default 25) |
| public interface ISharpClawTool | ||
| { | ||
| string Name { get; } | ||
| string Description { get; } | ||
| string InputSchemaJson { get; } | ||
| Task<string> ExecuteAsync(string input, ToolExecutionContext context, CancellationToken cancellationToken); | ||
| } |
There was a problem hiding this comment.
The ISharpClawTool interface shown here does not match the actual ISharpClawTool contract in src/SharpClaw.Code.Tools/Abstractions/ISharpClawTool.cs (which exposes ToolDefinition and ExecuteAsync(context, request)). This will mislead tool implementers. Please update the snippet to mirror the real interface and tool implementation pattern used in the codebase (e.g., SharpClawToolBase + ToolDefinition).
| "Provider": "Anthropic", | ||
| "Anthropic": { | ||
| "ApiKey": "<YOUR_ANTHROPIC_API_KEY>", | ||
| "Model": "claude-sonnet-4-5" |
There was a problem hiding this comment.
This example appsettings.json uses "SharpClaw:Provider" and "SharpClaw:Anthropic" keys, but the runtime binds provider options under "SharpClaw:Providers:*" (see ProvidersServiceCollectionExtensions). As-is, these settings won’t be picked up and the example likely won’t authenticate/configure the provider. Update to the correct section names (e.g., SharpClaw:Providers:Anthropic plus SharpClaw:Providers:Catalog:DefaultProvider).
| "Provider": "Anthropic", | |
| "Anthropic": { | |
| "ApiKey": "<YOUR_ANTHROPIC_API_KEY>", | |
| "Model": "claude-sonnet-4-5" | |
| "Providers": { | |
| "Catalog": { | |
| "DefaultProvider": "Anthropic" | |
| }, | |
| "Anthropic": { | |
| "ApiKey": "<YOUR_ANTHROPIC_API_KEY>", | |
| "Model": "claude-sonnet-4-5" | |
| } |
| "Provider": "Anthropic", | ||
| "Anthropic": { | ||
| "ApiKey": "<YOUR_ANTHROPIC_API_KEY>", | ||
| "Model": "claude-sonnet-4-5" |
There was a problem hiding this comment.
This example appsettings.json uses "SharpClaw:Provider" and "SharpClaw:Anthropic" keys, but the runtime binds provider options under "SharpClaw:Providers:*" (see ProvidersServiceCollectionExtensions). As-is, these settings won’t be picked up and the example likely won’t authenticate/configure the provider. Update to the correct section names (e.g., SharpClaw:Providers:Anthropic plus SharpClaw:Providers:Catalog:DefaultProvider).
| "Provider": "Anthropic", | |
| "Anthropic": { | |
| "ApiKey": "<YOUR_ANTHROPIC_API_KEY>", | |
| "Model": "claude-sonnet-4-5" | |
| "Providers": { | |
| "Catalog": { | |
| "DefaultProvider": "Anthropic" | |
| }, | |
| "Anthropic": { | |
| "ApiKey": "<YOUR_ANTHROPIC_API_KEY>", | |
| "Model": "claude-sonnet-4-5" | |
| } |
| "Provider": "Anthropic", | ||
| "Anthropic": { | ||
| "ApiKey": "<YOUR_ANTHROPIC_API_KEY>", | ||
| "Model": "claude-sonnet-4-5" |
There was a problem hiding this comment.
This example appsettings.json uses "SharpClaw:Provider" and "SharpClaw:Anthropic" keys, but the runtime binds provider options under "SharpClaw:Providers:*" (see ProvidersServiceCollectionExtensions). As-is, these settings won’t be picked up and the example likely won’t authenticate/configure the provider. Update to the correct section names (e.g., SharpClaw:Providers:Anthropic plus SharpClaw:Providers:Catalog:DefaultProvider).
| "Provider": "Anthropic", | |
| "Anthropic": { | |
| "ApiKey": "<YOUR_ANTHROPIC_API_KEY>", | |
| "Model": "claude-sonnet-4-5" | |
| "Providers": { | |
| "Catalog": { | |
| "DefaultProvider": "Anthropic" | |
| }, | |
| "Anthropic": { | |
| "ApiKey": "<YOUR_ANTHROPIC_API_KEY>", | |
| "Model": "claude-sonnet-4-5" | |
| } |
Summary
Closes all 7 Phase 1 gaps from the PRD, transforming SharpClaw Code from a streaming wrapper into a full coding agent runtime with tool-calling, conversation history, and production infrastructure.
P0 — Tool-Calling Loop + Conversation History
ChatMessage,ContentBlock,ContentBlockKind,ProviderToolDefinitionfor structured conversation historyProviderRequestnow carriesMessages,Tools,MaxTokens;ProviderEventcarries tool-use metadatatool_usecontent blocks from streaming,AnthropicMessageBuildermaps messages/tools to SDK typesFunctionCallContentfrom MEAI streaming,OpenAiMessageBuildermaps to MEAI typesIToolExecutorwith permission enforcement and event publishingProviderBackedAgentKernelnow implements multi-iteration loop (stream → detect tool-use → execute → feed back → repeat, up to 25 iterations)ConversationHistoryAssemblerbuildsChatMessage[]from session events;ContextWindowManagerapplies token-aware truncation (100K budget)P1 — Infrastructure
P2 — Production Hardening
ResilientProviderDecoratorwith exponential backoff + jitter retry, 429/Retry-After handling, circuit breaker (open/half-open/closed)SharpClawActivitySource+TurnActivityScope+ProviderActivityScope(OpenTelemetry spans),SharpClawMeterSource(counters + histograms for tokens, duration, tool invocations),NdjsonTraceFileSinkfor offline trace analysisStats
Test plan
dotnet build SharpClawCode.sln— 0 errorsdotnet test SharpClawCode.sln— 192/192 passtool_call_roundtrip) verifies end-to-end loop🤖 Generated with Claude Code